Análisis exploratorio Covid INS Colombia

Datos: ins Colombia

In [1]:
import numpy as np
import pandas as pd
import seaborn as sns
from urllib.request import urlopen
import json
from sodapy import Socrata
import plotly.express as px
import plotly.graph_objs as go
import matplotlib.pyplot as plt
from country_list import countries_for_language
import unidecode
import topojson
from topojson import geometry
plt.style.use('ggplot')
sns.set_context("talk")
In [2]:
spa = dict(countries_for_language("es"))
for k,v in spa.items():
    spa.update({k: unidecode.unidecode(v.upper())})
    

eng = dict(countries_for_language("en"))
In [3]:
def load_colombia_df():
    client = Socrata("www.datos.gov.co", None)  # https://www.datos.gov.co/es/profile/edit/developer_settings   por si no funciona
    results = client.get("gt2j-8ykr", limit=100000)
    results_df = pd.DataFrame.from_records(results)
    return results_df
In [4]:
df_col = load_colombia_df()
df_col.to_csv("ins_covid.csv", index=False)
WARNING:root:Requests made without an app_token will be subject to strict throttling limits.
In [5]:
df_col.head()
Out[5]:
id_de_caso fecha_de_notificaci_n codigo_divipola ciudad_de_ubicaci_n departamento atenci_n edad sexo tipo estado pa_s_de_procedencia fis fecha_de_muerte fecha_diagnostico fecha_recuperado fecha_reporte_web
0 1 2020-03-02T00:00:00.000 11001 Bogotá D.C. Bogotá D.C. Recuperado 19 F Importado Leve ITALIA 2020-02-27T00:00:00.000 - - 2020-03-06T00:00:00.000 2020-03-13T00:00:00.000 2020-03-06T00:00:00.000
1 2 2020-03-06T00:00:00.000 76111 Guadalajara de Buga Valle del Cauca Recuperado 34 M Importado Leve ESPAÑA 2020-03-04T00:00:00.000 - - 2020-03-09T00:00:00.000 2020-03-19T00:00:00.000 2020-03-09T00:00:00.000
2 3 2020-03-07T00:00:00.000 5001 Medellín Antioquia Recuperado 50 F Importado Leve ESPAÑA 2020-02-29T00:00:00.000 - - 2020-03-09T00:00:00.000 2020-03-15T00:00:00.000 2020-03-09T00:00:00.000
3 4 2020-03-09T00:00:00.000 5001 Medellín Antioquia Recuperado 55 M Relacionado Leve COLOMBIA 2020-03-06T00:00:00.000 - - 2020-03-11T00:00:00.000 2020-03-26T00:00:00.000 2020-03-11T00:00:00.000
4 5 2020-03-09T00:00:00.000 5001 Medellín Antioquia Recuperado 25 M Relacionado Leve COLOMBIA 2020-03-08T00:00:00.000 - - 2020-03-11T00:00:00.000 2020-03-23T00:00:00.000 2020-03-11T00:00:00.000
In [6]:
def preprocess_df(df):
    df = df.rename(columns={"fecha_diagnostico": "Fecha de diagnóstico",
                            "ciudad_de_ubicaci_n": "ciudad",
                            "fecha_de_notificaci_on": "Fecha de notificacion",
                            "atenci_n": "atencion"})
    
    df["sexo"] = df["sexo"].str.upper()
    df["estado"] = df["estado"].str.upper()
    df["atencion"] = df["atencion"].str.upper()
    df["tipo"] = df["tipo"].str.upper()
    df["edad"] = df["edad"].astype(int)
    
    df["Fecha de diagnóstico"] = pd.to_datetime(df["Fecha de diagnóstico"], errors="coerce")
    df["fecha_recuperado"] = pd.to_datetime(df["fecha_recuperado"], errors="coerce")
    df["fecha_de_muerte"] = pd.to_datetime(df["fecha_de_muerte"], errors="coerce")
    df["asintomatico"] = df["fis"] == "Asintomático"
    df["asintomatico"] = df["asintomatico"].astype(int)
    df["fis"] = pd.to_datetime(df["fis"], errors="coerce")
    df["tiempo recuperacion"] = df["fecha_recuperado"] - df["fis"]
    df["tiempo recuperacion"] = df["tiempo recuperacion"].dt.days
    
    df["tiempo muerte"] = df["fecha_de_muerte"] - df["fis"]
    df["tiempo muerte"] = df["tiempo muerte"].dt.days
    return df
In [7]:
df_col = preprocess_df(df_col)
In [8]:
df_leve = df_col[df_col["estado"] == "LEVE"]
df_moderado = df_col[df_col["estado"] == "MODERADO"]
df_fallecido = df_col[df_col["estado"] == "FALLECIDO"]
df_grave = df_col[df_col["estado"] == "GRAVE"]
df_asintoma = df_col[df_col["asintomatico"] == True]

Covid por departamento

In [9]:
def generar_cuenta_colombia(df_data):
    lista = ["Amazonas","Antioquia","Arauca","Atlántico","Bogotá D.C.","Bolívar",
    "Boyacá","Caldas","Caquetá","Casanare","Cauca","Cesar","Chocó",
    "Córdoba","Cundinamarca","Guainía","Guaviare","Huila","La Guajira","Magdalena",
    "Meta","Nariño","Norte de Santander","Putumayo","Quindío","Risaralda","San Andrés y Providencia",
    "Santander","Sucre","Tolima","Valle del Cauca","Vaupés","Vichada"]
    lista = [depto.upper() for depto in lista]
    ceros = [0]*len(lista)
    df_ceros = pd.DataFrame({"NOMBRE_DPT":lista, "cuenta_ceros":ceros})

    # df_data = pd.read_csv("data/Casos1.csv")
    df_data = df_data.rename(columns={"departamento": "NOMBRE_DPT"})
    df_data["NOMBRE_DPT"] = df_data["NOMBRE_DPT"].str.upper()
    df_cuenta = pd.DataFrame(df_data.groupby("NOMBRE_DPT")["id_de_caso"].count()).reset_index().rename(columns={"id_de_caso": "cuenta"})
    
    df_merge = df_ceros.merge(df_cuenta, on="NOMBRE_DPT", how="left")


    df_merge["total"] = df_merge["cuenta"] + df_merge["cuenta_ceros"]
    df_merge = df_merge.drop(["cuenta", "cuenta_ceros"], axis=1)
    nombres_dict = {"BOGOTÁ D.C.": "SANTAFE DE BOGOTA D.C",
                    "VALLE": "VALLE DEL CAUCA"}
    for dept in nombres_dict:
        df_merge = df_merge.replace(dept, nombres_dict[dept])
    df_merge = df_merge.fillna(0)
    df_merge['NOMBRE_DPT'] = df_merge['NOMBRE_DPT'].str.normalize('NFKD').str.encode('ascii', errors='ignore').str.decode('utf-8')
    df_merge = df_merge.replace("NARINO", "NARIÑO")
    return df_merge

def generar_mapa_colombia_cuenta(df_data):
    df_merge = generar_cuenta_colombia(df_data)
    with urlopen('https://gist.githubusercontent.com/john-guerra/43c7656821069d00dcbc/raw/be6a6e239cd5b5b803c6e7c2ec405b793a9064dd/Colombia.geo.json') as response:
        counties = json.load(response)

    fig = px.choropleth(df_merge, geojson=counties, color="total",
                        locations="NOMBRE_DPT", featureidkey="properties.NOMBRE_DPT",
                        projection="mercator",scope="south america",color_continuous_scale=px.colors.sequential.Blues,
                        range_color = [0,300]
                    )
    fig.update_geos(fitbounds="locations", visible=False, showcountries=True, countrycolor="Black",
        showsubunits=True)
    fig.update_layout(
        title_text = 'Confirmados en Colombia',
        font=dict(
            family="Courier New, monospace",
            size=25,
            color="#7f7f7f"
        )
    )
    return fig
In [10]:
fig = generar_mapa_colombia_cuenta(df_col)
fig.show()

Confirmados en Antioquia

In [11]:
with urlopen('https://raw.githubusercontent.com/davidbetancur8/Antioquia_dash/master/colombia-municipios.json') as response:
        topoJSON = json.load(response)
        
def create_ant_df(df_data):
    geometries = topoJSON["objects"]["mpios"]["geometries"]
    geometries_ant = []
    ciudades = []
    for mpio in geometries:
        if mpio["properties"]["dpt"] == "ANTIOQUIA":
            geometries_ant.append(mpio)
            ciudades.append(mpio["properties"]["name"])
    topoJSON["objects"]["mpios"]["geometries"] = geometries_ant
    df_ciudades_ant = pd.DataFrame({"ciudad": ciudades})
    df_data_ant = df_data[df_data["departamento"] == "Antioquia"].loc[:,["Fecha de diagnóstico", "ciudad"]]
    df_data_ant["ciudad"] = df_data_ant["ciudad"].str.normalize('NFKD').str.encode('ascii', errors='ignore').str.decode('utf-8')
    df_data_ant["ciudad"] = df_data_ant["ciudad"].str.upper()
    df_data_ant_agg = df_data_ant.groupby("ciudad").count().reset_index().rename(columns={"Fecha de diagnóstico": "cuenta"})
    df_ciudades_ant_cuenta = df_ciudades_ant.merge(df_data_ant_agg, on="ciudad", how="left").fillna(0)
    df_ciudades_ant_cuenta[df_ciudades_ant_cuenta["ciudad"] == "MEDELLIN"]
    
    df_ciudades_ant_cuenta = df_ciudades_ant.merge(df_data_ant_agg, on="ciudad", how="left").fillna(0)
    df_ciudades_ant_cuenta[df_ciudades_ant_cuenta["ciudad"] == "MEDELLIN"]
    
    topo_features = topoJSON['objects']["mpios"]['geometries']
    scale = topoJSON['transform']['scale']
    translation = topoJSON['transform']['translate']
    geoJSON=dict(type= 'FeatureCollection', 
             features = [])

    for k, tfeature in enumerate(topo_features):
        geo_feature = dict(id=k, type= "Feature")
        geo_feature['properties'] = tfeature['properties']
        geo_feature['geometry'] = geometry(tfeature, topoJSON['arcs'], scale, translation)    
        geoJSON['features'].append(geo_feature) 
        
    return df_ciudades_ant_cuenta, geoJSON
In [12]:
df_ciudades_ant_cuenta, geoJSON = create_ant_df(df_col)
In [13]:
fig = px.choropleth(df_ciudades_ant_cuenta, geojson=geoJSON, color="cuenta",
                    locations="ciudad", featureidkey="properties.name",
                    projection="mercator",scope="south america",color_continuous_scale=px.colors.sequential.Blues,
                    range_color = [0,100]
                   )
fig.update_geos(fitbounds="locations", visible=True, showcountries=True, countrycolor="Black",
    showsubunits=True)
fig.update_layout(
    title_text = 'Confirmados Antioquia',
    font=dict(
        family="Courier New, monospace",
        size=25,
        color="#7f7f7f"
    )
)
fig.show()

Importados

In [14]:
def get_code(row):
    try:
        indice = list(spa.values()).index(row["País de procedencia"])
        codigo = list(spa.keys())[indice]
        return codigo
    except:
        # print(row)
        return "CO"

def get_lat_long(row, df_lat_lon):
    try:
        cod =row["codigos"]
        row_cod = df_lat_lon[df_lat_lon["code"] == cod]
        row["lat"] = row_cod["lat"].values[0]
        row["long"] = row_cod["lon"].values[0]
    except:
        print(row_cod)
        print(row)
    return row

def generar_cuenta_importados(df_data):
    df_lat_lon = pd.read_csv("data/lat_long.csv")
    # df_data = pd.read_csv("data/Casos1.csv")
    df_data = df_data.rename(columns={"pa_s_de_procedencia": "País de procedencia"})
    df_data = df_data.loc[:,["sexo", "País de procedencia"]]
    df_data["País de procedencia"] = df_data["País de procedencia"].fillna("Colombia")
    df_data["País de procedencia"] = df_data["País de procedencia"].apply(lambda x: x.split("-")[0])
    df_data["País de procedencia"] = df_data["País de procedencia"].str.strip()
    df_data["País de procedencia"] = df_data["País de procedencia"].str.upper()
    df_data = df_data.replace("ESTADOS UNIDOS DE AMERICA", "ESTADOS UNIDOS")
    df_data = df_data.replace("ESPAÑA", "ESPANA")
    df_data = df_data.replace("CURAZAO", "CURAÇAO")
    df_data["codigos"] = df_data.apply(get_code, axis=1)
    df_data["name"] = df_data.apply(lambda x: eng[x["codigos"]], axis=1)
    paises = df_data.apply(get_lat_long, df_lat_lon=df_lat_lon, axis=1).loc[:,["name", "lat", "long"]]
    paises = paises.drop_duplicates()
    df_data = df_data.merge(paises, on="name", how="left")
    df_data["end_lat"] = 2.889443
    df_data["end_long"] = -73.783892
    df_data_grouped = df_data.groupby(["name", "lat", "long", "end_lat", "end_long"]).count().reset_index().drop(["País de procedencia", "codigos"], axis=1)
    df_data_grouped = df_data_grouped.rename(columns={"sexo":"cuenta"})
    df_data_grouped["texto"] = df_data_grouped["name"] + ", number of confirmed: " + df_data_grouped["cuenta"].astype(str)
    return df_data_grouped
In [15]:
def generar_mapa_importados(df_data):
    df_data_grouped = generar_cuenta_importados(df_data)
    fig = go.Figure()
    for i in range(len(df_data_grouped)):
        fig.add_trace(
            go.Scattergeo(
                lon = [df_data_grouped['long'][i], df_data_grouped['end_long'][i]],
                lat = [df_data_grouped['lat'][i], df_data_grouped['end_lat'][i]],
                mode = 'lines',
                line = dict(width = 2*(np.log(df_data_grouped['cuenta'][i]) / np.log(df_data_grouped['cuenta'].max())),
                            color = '#051C57'),
                opacity = 1,
            )
        )

    fig.add_trace(go.Scattergeo(
        lon = df_data_grouped['long'],
        lat = df_data_grouped['lat'],
        text = df_data_grouped['texto'],
        hoverinfo = "text",
        mode = 'markers',
        marker = dict(
            size = 10,
            opacity = (np.log(df_data_grouped['cuenta']) / np.log(df_data_grouped['cuenta'].max())),
            color="#051C57"
        )))

    fig.update_layout(
        title_text = 'Procedencia de confirmados',
        showlegend = False,
        font=dict(
            family="Courier New, monospace",
            size=28,
            color="#7f7f7f"
        ),
        geo = dict(
            scope = 'world',
            showland = True,
            landcolor = 'rgb(243, 243, 243)',
            countrycolor = 'rgb(204, 204, 204)',
        ),
    )
    return fig
In [16]:
fig = generar_mapa_importados(df_col)
fig.show()

Cuenta por dia

In [17]:
cuenta = pd.DataFrame(df_col.groupby("Fecha de diagnóstico")["id_de_caso"].count()).reset_index()
cuenta = cuenta.rename(columns={"id_de_caso":"cuenta"})
cuenta.head()
Out[17]:
Fecha de diagnóstico cuenta
0 2020-03-06 1
1 2020-03-09 2
2 2020-03-11 6
3 2020-03-12 5
4 2020-03-13 5
In [18]:
fig = px.bar(data_frame=cuenta, x="Fecha de diagnóstico", y="cuenta")
fig.update_layout(
    title_text = 'Confirmados por día en Colombia',
    font=dict(
        family="Courier New, monospace",
        size=10,
        color="#7f7f7f"
    ),
    titlefont= dict(size= 25)

)
fig.show("notebook")

Recuperados por dia

In [46]:
df_changed = df_col.copy()
df_changed["fecha_recuperado"] = df_changed["fecha_recuperado"].dt.date
cuenta_rec = pd.DataFrame(df_changed.groupby("fecha_recuperado")["id_de_caso"].count()).reset_index()
cuenta_rec = cuenta_rec.rename(columns={"id_de_caso":"cuenta"})
cuenta_rec.head()
Out[46]:
fecha_recuperado cuenta
0 2020-03-13 1
1 2020-03-14 1
2 2020-03-15 1
3 2020-03-17 1
4 2020-03-19 1
In [47]:
fig = px.bar(data_frame=cuenta_rec, x="fecha_recuperado", y="cuenta")
fig.update_layout(
    title_text = 'Muertes por día en Colombia',
    font=dict(
        family="Courier New, monospace",
        size=10,
        color="#7f7f7f"
    ),
    titlefont= dict(size= 25)

)
fig.show()

Muertes por dia

In [21]:
cuenta_muerte = pd.DataFrame(df_col.groupby("fecha_de_muerte")["id_de_caso"].count()).reset_index()
cuenta_muerte = cuenta_muerte.rename(columns={"id_de_caso":"cuenta"})
cuenta_muerte.head()
Out[21]:
fecha_de_muerte cuenta
0 2020-03-16 1
1 2020-03-22 1
2 2020-03-23 1
3 2020-03-24 1
4 2020-03-25 4
In [22]:
fig = px.bar(data_frame=cuenta_muerte, x="fecha_de_muerte", y="cuenta")
fig.update_layout(
    title_text = 'Muertes por día en Colombia',
    font=dict(
        family="Courier New, monospace",
        size=10,
        color="#7f7f7f"
    ),
    titlefont= dict(size= 25)

)
fig.show()

Tiempo de recuperacion

In [23]:
plt.figure(figsize=(15,7))
sns.countplot(df_col["tiempo recuperacion"], palette="Set3")
plt.title("Tiempo de recuperación")
plt.xticks(rotation=90)
plt.show()

Tiempo de muerte

In [24]:
plt.figure(figsize=(15,7))
sns.countplot(df_col["tiempo muerte"], palette="Set3")
plt.title("Tiempo de muerte")
plt.xticks(rotation=90)
plt.show()

Sexo

In [25]:
plt.figure(figsize=(10,7))
ax = sns.countplot(x = "sexo", hue="estado", data = df_col, palette="Set3")
total = df_col.shape[0]

Edad

In [26]:
plt.figure(figsize=(15,7))
sns.distplot(df_col["edad"])
plt.title("Distribucion por edad para todos los estados")
plt.show()
In [27]:
f, axes = plt.subplots(3, 2, figsize=(15,10))

sns.distplot(df_col["edad"], ax=axes[0,0])
axes[0,0].title.set_text('Total')

sns.distplot(df_fallecido["edad"], ax=axes[0,1])
axes[0,1].title.set_text('Fallecidos')

sns.distplot(df_leve["edad"], ax=axes[1,0])
axes[1,0].title.set_text('Leve')

sns.distplot(df_moderado["edad"], ax=axes[1,1])
axes[1,1].title.set_text('Moderado')

sns.distplot(df_grave["edad"], ax=axes[2,0])
axes[2,0].title.set_text('Grave')

sns.distplot(df_asintoma["edad"], ax=axes[2,1])
axes[2,1].title.set_text('Asintomáticos')

plt.tight_layout()

f.suptitle("Distribucion por estados")
plt.show()

Asintomaticos

In [28]:
plt.figure(figsize=(15,7))
ax = sns.countplot(df_col["asintomatico"], palette="Set3")
total = df_col.shape[0]
for p in ax.patches:
    height = p.get_height()
    print(height)
    ax.text(p.get_x()+p.get_width()/2.,
            height + 40,
            '{:1.4f}%'.format((height/total)*100),
            ha="center")

plt.title("Cuenta de asintomáticos")
plt.show()
3920
229
In [29]:
df_col.columns
Out[29]:
Index(['id_de_caso', 'fecha_de_notificaci_n', 'codigo_divipola', 'ciudad',
       'departamento', 'atencion', 'edad', 'sexo', 'tipo', 'estado',
       'pa_s_de_procedencia', 'fis', 'fecha_de_muerte', 'Fecha de diagnóstico',
       'fecha_recuperado', 'fecha_reporte_web', 'asintomatico',
       'tiempo recuperacion', 'tiempo muerte'],
      dtype='object')
In [30]:
df_col["tipo"].unique()
Out[30]:
array(['IMPORTADO', 'RELACIONADO', 'EN ESTUDIO', 'N.D.'], dtype=object)
In [31]:
df_col_nums = df_col.loc[:,["atencion", "edad", "sexo", "tipo", 
                            "estado", "asintomatico", "tiempo recuperacion", "tiempo muerte"]]

df_col_nums = pd.get_dummies(df_col_nums)
df_col_nums = df_col_nums.fillna(0)
df_col_nums
Out[31]:
edad asintomatico tiempo recuperacion tiempo muerte atencion_CASA atencion_FALLECIDO atencion_HOSPITAL atencion_HOSPITAL UCI atencion_RECUPERADO sexo_F sexo_M tipo_EN ESTUDIO tipo_IMPORTADO tipo_N.D. tipo_RELACIONADO estado_FALLECIDO estado_GRAVE estado_LEVE estado_MODERADO
0 19 0 15.0 0.0 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0
1 34 0 15.0 0.0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0
2 50 0 15.0 0.0 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0
3 55 0 20.0 0.0 0 0 0 0 1 0 1 0 0 0 1 0 0 1 0
4 25 0 15.0 0.0 0 0 0 0 1 0 1 0 0 0 1 0 0 1 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
4144 47 0 0.0 0.0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0
4145 55 0 0.0 0.0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0
4146 24 0 0.0 0.0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0
4147 5 0 0.0 0.0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0
4148 46 0 0.0 0.0 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0

4149 rows × 19 columns

In [32]:
sns.set_context("talk")

corr = df_col_nums.corr().round(1)

mask = np.zeros_like(corr, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True

plt.figure(figsize=(18, 18))

cmap = sns.diverging_palette(240, 10, as_cmap=True)

sns.heatmap(corr, mask=mask, cmap=cmap, vmin=-1, vmax=1, center=0,annot=True)

plt.tight_layout()